package uts.sdk.modules.xsdRequest

import io.dcloud.uniapp.UniError
import io.dcloud.uts.UTSError
import io.dcloud.uts.UTSObject
import io.dcloud.uts.UTSPromise
import io.dcloud.uts.await
import io.dcloud.uts.wrapUTSPromise
import uts.sdk.modules.DCloudUniPrompt.ShowLoadingOptions
import io.dcloud.uniapp.extapi.hideLoading as uni_hideLoading
import io.dcloud.uniapp.extapi.showLoading as uni_showLoading

inline fun <reified A, reified D> innerCreateXRequest(
    baseOptions: XBaseRequestOptions,
    xRequestOptions: XRequestOptions<A, D>,
    instanceConfig: XOptions
): UTSPromise<D> {
    return wrapUTSPromise(suspend w@{
        val genericTypeD = object : io.dcloud.uts.gson.reflect.TypeToken<D>() {
        }.type
        val loading = instanceConfig.loading
        val _instanceConfig_loadingTitle = instanceConfig.loadingTitle
        val loadingTitle = if (_instanceConfig_loadingTitle == null) {
            ""
        } else {
            _instanceConfig_loadingTitle
        }
        val _instanceConfig_loadingMask = instanceConfig.loadingMask
        val loadingMask = if (_instanceConfig_loadingMask == null) {
            true
        } else {
            _instanceConfig_loadingMask
        }
        if (loading == true) {
            uni_showLoading(
                ShowLoadingOptions(
                    title = loadingTitle, mask = loadingMask
                )
            )
        }
        val assign = assignConfig(baseOptions, instanceConfig)
        val onRequest = xRequestOptions.onRequest
        val onRequestEnd = xRequestOptions.onRequestEnd
        val onRequestError = xRequestOptions.onRequestError
        val onRequestMonitor = xRequestOptions.onRequestMonitor
        val onRequestMonitorError = xRequestOptions.onRequestMonitorError
        val onSuccess = xRequestOptions.onSuccess
        var user = onRequest(assign)
        var once = await(createInstance<A>(user))
        var error = once.error
        if (null != error) {
            if (loading == true) {
                uni_hideLoading()
            }
            onRequestError(error, null)
            throw UTSError(error.errMsg)
        }
        var response = once.response!!
        //val reqIsSuccess = await(onRequestEnd(response))
		val reqIsSuccess = onRequestEnd(response)
        if (false == reqIsSuccess) {
            if (loading == true) {
                uni_hideLoading()
            }
            val errorImpl = UniError(
                "xsd-request",
                response.statusCode,
                "request_fail: onRequestEnd is not true"
            )
            onRequestError(errorImpl, response)
            throw UTSError(errorImpl.errMsg)
        }
        if (null == reqIsSuccess) {
            user = onRequest(user)
            once = await(createInstance<A>(user))
            error = once.error
            if (null != error) {
                if (loading == true) {
                    uni_hideLoading()
                }
                onRequestError(error, null)
                throw UTSError(error.errMsg)
            }
            response = once.response!!
        }
        if (null == response.data) {
            if (loading == true) {
                uni_hideLoading()
            }
            val errorImpl =
                UniError("xsd-request", response.statusCode, "request_fail: response.data is null")
            onRequestError(errorImpl, response)
            throw UTSError(errorImpl.errMsg)
        }
        val apiResponse = response.data!!
        val busIsSuccess = onRequestMonitor(apiResponse)
        if (!busIsSuccess) {
            if (loading == true) {
                uni_hideLoading()
            }
            val errorImpl = UniError(
                "xsd-request",
                response.statusCode,
                "request_fail: onRequestMonitor is not true"
            )
            onRequestMonitorError(apiResponse)
            throw UTSError(errorImpl.errMsg)
        }
        if (loading == true) {
            uni_hideLoading()
        }
        return@w UTSObject.toGenericType<D>(onSuccess(apiResponse), genericTypeD)
    })
}
